package com.george.caffeine.dao.redis;

import com.alibaba.fastjson.TypeReference;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.ZSetOperations;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @Title: RedisDao.java
 * @Description: Redis缓存接口
 * @Author: George
 * @Date: 2022/3/31 10:11
 */
public interface RedisDao {
    /**
     * get
     * @param key
     * @return
     */
    String get(Object key);

    /**
     * get
     * @param key
     * @param type
     * @param <T>
     * @return
     */
    <T> T get(Object key, Class<T> type);

    /**
     * get
     * @param key
     * @param typeReference
     * @param <T>
     * @return
     */
    <T> T get(Object key, TypeReference<T> typeReference);

    /**
     * getList
     * @param key
     * @param type
     * @param <T>
     * @return
     */
    <T> List<T> getList(Object key, Class<T> type);

    /**
     * getMap
     * @param key
     * @param typeReference
     * @param <K>
     * @param <V>
     * @return
     */
    <K,V> Map<K,V> getMap(Object key, TypeReference<V> typeReference);

    /**
     * multiGet
     * @param keys
     * @param type
     * @param <T>
     * @return
     */
    <T> List<T> multiGet(Collection<Object> keys, Class<T> type);

    /**
     * multiGet
     * @param keys
     * @param typeReference
     * @param <T>
     * @return
     */
    <T> List multiGet(Collection<Object> keys, TypeReference<T> typeReference);

    /**
     * existsKey
     * @param key
     * @return
     */
    Boolean existsKey(Object key);

    /**
     * delete
     * @param key
     */
    void delete(Object key);

    /**
     * keys
     * @param key
     * @return
     */
    Set<Object> keys(Object key);

    /**
     * put
     * @param key
     * @param value
     */
    void put(Object key, Object value);

    /**
     * put
     * @param key
     * @param value
     * @param timeout
     */
    void put(Object key, Object value, long timeout);

    /**
     * put
     * @param key
     * @param value
     * @param timeout
     * @param unit
     */
    void put(Object key, Object value, long timeout, TimeUnit unit);

    /**
     * multiPut
     * @param keyValue
     */
    void multiPut(Map<Object, Object> keyValue);

    /**
     * putIfAbsent
     * @param key
     * @param value
     * @return
     */
    Boolean putIfAbsent(Object key, Object value);

    /**
     * getAndSet
     * @param key
     * @param value
     * @return
     */
    String getAndSet(Object key, String value);

    /**
     * multiPutIfAbsent
     * @param keyValue
     * @return
     */
    Boolean multiPutIfAbsent(Map<Object, Object> keyValue);

    /**
     * expire
     * @param key
     * @param timeout
     * @param unit
     * @return
     */
    Boolean expire(Object key, long timeout, TimeUnit unit);

    /**
     * getExpire
     * @param key
     * @return
     */
    Long getExpire(Object key);

    /**
     * replace
     * @param key
     * @param value
     */
    void replace(Object key, Object value);

    /**
     * replace
     * @param key
     * @param value
     * @param timeout
     */
    void replace(Object key, Object value, long timeout);

    /**
     * replace
     * @param key
     * @param value
     * @param timeout
     * @param unit
     */
    void replace(Object key, Object value, long timeout, TimeUnit unit);

    /**
     * evict
     * @param key
     */
    void evict(Object key);

    /**
     * increment
     * @param key
     * @param offset
     * @return
     */
    long increment(Object key, long offset);

    /**
     * increment
     * @param key
     * @param hashKey
     * @param delta
     * @return
     */
    long increment(Object key, String hashKey, long delta);

    /**
     * add
     * @param key
     * @param valueList
     * @param <T>
     * @return
     */
    <T> List<T> add(String key, List<T> valueList);

    /**
     * members
     * @param key
     * @param type
     * @param <T>
     * @return
     */
    <T> List<T> members(String key, Class<T> type);

    /**
     * isMember
     * @param key
     * @param o
     * @return
     */
    boolean isMember(Object key, Object o);

    /**
     * sAdd
     * @param key
     * @param o
     * @return
     */
    Long sAdd(Object key, Object o);

    /**
     * leftPush
     * @param key
     * @param value
     */
    void leftPush(Object key, Object value);

    /**
     * rightPop
     * @param key
     * @return
     */
    String rightPop(Object key);

    /**
     * rightPop
     * @param key
     * @param size
     * @param type
     * @param <T>
     * @return
     */
    <T> List<T> rightPop(final Object key, final int size, Class<T> type);

    /**
     * length
     * @param key
     * @return
     */
    Long length(Object key);

    /**
     * ttl
     * @param key
     * @return
     */
    Long ttl(Object key);

    /**
     * addSet
     * @param key
     * @param value
     * @param score
     */
    void addSet(Object key, String value, double score);

    /**
     * addSet
     * @param key
     * @param tuples
     */
    void addSet(Object key, Set<ZSetOperations.TypedTuple<String>> tuples);

    /**
     * getSetSize
     * @param key
     * @return
     */
    Long getSetSize(Object key);

    /**
     * getSetByRevRange
     * @param key
     * @param start
     * @param end
     * @return
     */
    Set<String> getSetByRevRange(Object key, long start, long end);

    /**
     * getSetByRange
     * @param key
     * @param start
     * @param end
     * @return
     */
    Set<String> getSetByRange(Object key, long start, long end);

    /**
     * clearZSet
     * @param key
     */
    void clearSet(Object key);

    /**
     * setIfAbsent 对应redis setnx命令
     * @param key
     * @param value
     * @return
     */
    boolean setIfAbsent(Object key, Object value);

    /**
     * expireByPipe
     * @param data
     * @param <K>
     */
    <K> void expireByPipe(final Map<K, Long> data);

    /**
     * rightPopByPipe
     * @param key
     * @param size
     * @param type
     * @param <T>
     * @return
     */
    <T> List<T> rightPopByPipe(final Object key, final int size, Class<T> type);

    /**
     * hashMultiPutByPipe
     * @param kv
     * @param <T>
     */
    <T> void hashMultiPutByPipe(Map<Object, T> kv);

    /**
     * hashMultiGetByPipe
     * @param keys
     * @param type
     * @param <T>
     * @return
     */
    <T> List<T> hashMultiGetByPipe(Collection<Object> keys, Class<T> type);

    /**
     * multiGetByPipe
     * @param keys
     * @param clazz
     * @param <T>
     * @param <U>
     * @return
     */
    <T, U> List<T> multiGetByPipe(List<U> keys, Class<T> clazz);

    /**
     * multiPutByPipe
     * @param m
     * @param timeout
     * @param unit
     * @param <K>
     * @param <V>
     */
    <K, V> void multiPutByPipe(Map<K, V> m, long timeout, TimeUnit unit);

    /**
     * execute
     * @param action
     * @param <T>
     * @return
     */
    <T> T execute(RedisCallback<T> action);

    /**
     * 根据key前缀进行删除
     *
     * @param prefix key的前缀
     */
    void deleteByPrefix(String prefix);
}